/*
 * Copyright 2008 Lucas Tan.
 * This copyright notice must always remain intact whenever you use or distribute 
 * the source code contained in this file.
 * Any usage of any code in this file, either in derived work or
 * through the use of external linkage,
 * must always be credited with the author's name.
 * 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 * DEALINGS IN THE SOFTWARE.
 * 
 * */
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;

namespace PassKeeper.Cryptography
{
	/// <summary>
	/// Static cryptographically secure random number generator class.
	/// </summary>
	public static class RNG 
	{
		private static readonly RandomNumberGenerator _rng;

		static RNG()
		{
			_rng = new RNGCryptoServiceProvider();
		}

		public static void GetBytes(byte[] data)
		{
			_rng.GetBytes(data);
		}

		public static void GetBytes(byte[] data, int offset, int count)
		{
			if (data == null)
			{
				throw new ArgumentNullException("data");
			}

			if (offset < 0)
			{
				throw new ArgumentOutOfRangeException("offset", "Cannot be negative.");
			}

			if (count < 0 || count > data.Length)
			{
				throw new ArgumentException("Invalid value.", "count");
			}

			if (data.Length - count < offset)
			{
				throw new ArgumentException("Buffer is too small to hold data at the specified index." );
			}

			if (count > 0)
			{
				byte[] tmp = new byte[count];

				_rng.GetBytes(tmp);

				Buffer.BlockCopy(tmp, 0, data, offset, count);
			}
		}

		public static void GetNonZeroBytes(byte[] data)
		{
			_rng.GetNonZeroBytes(data);
		}

		public static void GetNonZeroBytes(byte[] data, int offset, int count)
		{
			if (data == null)
			{
				throw new ArgumentNullException("data");
			}

			if (offset < 0)
			{
				throw new ArgumentOutOfRangeException("offset", "Cannot be negative.");
			}

			if (count < 0 || count > data.Length)
			{
				throw new ArgumentException("Invalid value.", "count");
			}

			if (data.Length - count < offset)
			{
				throw new ArgumentException("Buffer is too small to hold data at the specified index.");
			}

			if (count > 0)
			{
				byte[] tmp = new byte[count];

				_rng.GetNonZeroBytes(tmp);

				Buffer.BlockCopy(tmp, 0, data, offset, count);
			}
		}
	}
}
